The problem with _beginthread When you develop a multi-threaded application using the Win32 API, you normally need to use your compiler's run time library function called _beginthread, rather than the Win32 API function CreateThread. This is because the run-time library needs to do per-thread initialization and cleanup, which it can't do if you use the CreateThread API directly. For instance, if your program uses C++ exceptions, the run-time library needs to initialize the exception handling mechanism for that thread. Also, the run-time library uses global variables like internally for functions like strtok, so the run-time library must allocate and initialize a copy of these variables for each thread that uses the RTL. Both CreateThread and _beginthread return a handle to a thread. The handle is a magic cookie for an operating system object that represents the thread. This handle can be used to check the status of the thread, or it can be used to wait for a thread to complete if you use one of the WaitForXXX API functions. When you get the the handle from CreateThread, you are responsible for closing the handle using CloseHandle function. If you don't close the handle when you don't need it anymore, you have used up part of the operating system's resources which are not going to be released until your application terminates. One of the things that _beginthread does for you is that it closes the handle returned by CreateThread when the thread terminates, either by returning from the thread function or calling _endthread. This relieves you of the responsibility of closing that thread handle. However, the problem with the handle returned by _beginthread is that it is possible that it becomes invalid before you use it, because the thread started running then terminated. If you are lucky, the WaitForXXX might return an ERROR_INVALID_HANDLE, but sometimes the result is a hang. If you need a valid thread handle from _beginthread, there is a workaround. In the Borland C++ run-time library, there is a function called _beginthreadNT, and in the Visual C++ run-time library there is a function called _beginthreadex which have parameters additional to what _beginthread uses. One of these parameters is the creation flag that is passed to CreateThread. This flag can be CREATE_SUSPENDED, which causes the thread not to run until you call the ResumeThread function. Once you create a the thread in a suspended state, you can use the DuplicateHandle function which creates handle that represents the same object as the original handle. Once you have duplicated the handle, you can then allow the thread to run by calling ResumeThread. This needs to be done while the thread is in a suspended state because you don't want the thread to run and possibly terminate before you get a chance to duplicate the original handle. The handle returned by DuplicateHandle will be valid until you close it with CloseHandle. Listing 1 (bt.c) is the source code to a Win32 console mode application that demonstrates this technique. // listing 1 bt.c // note - make sure the multi-threaded library option // is on in your compiler's IDE settings. #include #include #include HANDLE beginthread_handle( #ifdef __BORLANDC__ void _USERENTRY (*start_address)(void *), #else unsigned (__stdcall *start_address)(void *), #endif unsigned stack_size, void *arglist ) { DWORD id; HANDLE h1 = (HANDLE) #ifdef __BORLANDC__ _beginthreadNT(start_address,stack_size, arglist,NULL,CREATE_SUSPENDED,&id); #else // for Visual C++ and compatibles _beginthreadex(NULL,stack_size,start_address, arglist,CREATE_SUSPENDED,&id); #endif HANDLE h2 = INVALID_HANDLE_VALUE; if( h1 != INVALID_HANDLE_VALUE ) { DuplicateHandle(GetCurrentProcess(),h1, GetCurrentProcess(),&h2,0,FALSE, DUPLICATE_SAME_ACCESS); ResumeThread(h1); } return h2; } #ifdef __BORLANDC__ void thread( void *arg ) #else unsigned __stdcall thread( void * arg ) #endif { printf("new thread called\n"); #ifndef __BORLANDC__ return 0; #endif } int main(void) { HANDLE h = beginthread_handle(thread,4096,NULL); if(h!=INVALID_HANDLE_VALUE) { printf("waiting on new thread\n"); WaitForSingleObject(h,INFINITE); printf("new thread is signaled\n"); CloseHandle(h); } return 0; }